﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

namespace ToddMcDermid.SSIS
{
    public partial class ReplacingDataConversionEditor : Form
    {
        #region Private Variables
        private ReplacingDataConversionConfiguration _configuration;
        #endregion

        #region Constructor
        public ReplacingDataConversionEditor(IDTSComponentMetaData100 componentMetaData)
        {
            InitializeComponent();
            this._configuration = new ReplacingDataConversionConfiguration(componentMetaData);
            this._configuration.Validate();
        }
        #endregion

        #region Form Events
        #region Form Load
        private void ReplacingDataConversionEditor_Load(object sender, EventArgs e)
        {
            #region Setup Simple Conversion Tab
            #region Set up Source Data Type Combo
            this.cboSimpleSourceDataType.Items.Clear();
            this.cboSimpleSourceDataType.DisplayMember = "CompleteName";
            List<DtsDataTypes.DataTypeDescriptionStruct> sourceTypes = new List<DtsDataTypes.DataTypeDescriptionStruct>();
            foreach (ColumnConversionConfig columnConversionConfig in this._configuration.CustomProperties.ColumnConversionConfigs)
            {
                DtsDataTypes.DataTypeDescriptionStruct columnType = DtsDataTypes.GetDataTypeDescriptionStruct(columnConversionConfig.InDataType);
                if (!sourceTypes.Contains(columnType))
                {
                    sourceTypes.Add(columnType);
                }
            }
            foreach (DtsDataTypes.DataTypeDescriptionStruct dataTypeDescription in sourceTypes)
            {
                this.cboSimpleSourceDataType.Items.Add(dataTypeDescription);
            }
            this.cboSimpleSourceDataType.SelectedItem = DtsDataTypes.GetDataTypeDescriptionStruct(DataType.DT_WSTR);
            if (this.cboSimpleSourceDataType.SelectedIndex < 0)
            {
                this.cboSimpleSourceDataType.SelectedIndex = 0;
            }
            #endregion

            #region Set up Source Length Combo
            List<int> sourceLengths = new List<int>();
            foreach (ColumnConversionConfig columnConversionConfig in this._configuration.CustomProperties.ColumnConversionConfigs)
            {
                DtsDataTypes.DataTypeDescriptionStruct columnType = DtsDataTypes.GetDataTypeDescriptionStruct(columnConversionConfig.InDataType);
                if (columnType.HasLength && !sourceLengths.Contains(columnConversionConfig.InLength))
                {
                    sourceLengths.Add(columnConversionConfig.InLength);
                }
            }
            sourceLengths.Sort();
            this.cboSimpleSourceLength.Items.Clear();
            this.cboSimpleSourceLength.Items.Add("any");
            for (int index = 0; index < sourceLengths.Count; index++)
            {
                this.cboSimpleSourceLength.Items.Add(sourceLengths[index].ToString());
            }
            this.cboSimpleSourceLength.SelectedIndex = 0;
            #endregion

            #region Set up Source CodePage Combo
            List<int> sourceCodePages = new List<int>();
            foreach (ColumnConversionConfig columnConversionConfig in this._configuration.CustomProperties.ColumnConversionConfigs)
            {
                DtsDataTypes.DataTypeDescriptionStruct columnType = DtsDataTypes.GetDataTypeDescriptionStruct(columnConversionConfig.InDataType);
                if (columnType.HasCodePage && !sourceCodePages.Contains(columnConversionConfig.InCodePage))
                {
                    sourceCodePages.Add(columnConversionConfig.InCodePage);
                }
            }
            sourceCodePages.Sort();
            this.cboSimpleSourceCodePage.Items.Clear();
            this.cboSimpleSourceCodePage.Items.Add("any");
            for (int index = 0; index < sourceCodePages.Count; index++)
            {
                this.cboSimpleSourceCodePage.Items.Add(sourceCodePages[index].ToString());
            }
            this.cboSimpleSourceCodePage.SelectedIndex = 0;
            #endregion

            #region Set up Source Precision Combo
            List<int> sourcePrecisions = new List<int>();
            foreach (ColumnConversionConfig columnConversionConfig in this._configuration.CustomProperties.ColumnConversionConfigs)
            {
                DtsDataTypes.DataTypeDescriptionStruct columnType = DtsDataTypes.GetDataTypeDescriptionStruct(columnConversionConfig.InDataType);
                if (columnType.HasPrecision && !sourcePrecisions.Contains(columnConversionConfig.InPrecision))
                {
                    sourcePrecisions.Add(columnConversionConfig.InPrecision);
                }
            }
            sourcePrecisions.Sort();
            this.cboSimpleSourcePrecision.Items.Clear();
            this.cboSimpleSourcePrecision.Items.Add("any");
            for (int index = 0; index < sourcePrecisions.Count; index++)
            {
                this.cboSimpleSourcePrecision.Items.Add(sourcePrecisions[index].ToString());
            }
            this.cboSimpleSourcePrecision.SelectedIndex = 0;
            #endregion

            #region Set up Source Scale Combo
            List<int> sourceScales = new List<int>();
            foreach (ColumnConversionConfig columnConversionConfig in this._configuration.CustomProperties.ColumnConversionConfigs)
            {
                DtsDataTypes.DataTypeDescriptionStruct columnType = DtsDataTypes.GetDataTypeDescriptionStruct(columnConversionConfig.InDataType);
                if (columnType.HasScale && !sourceScales.Contains(columnConversionConfig.InScale))
                {
                    sourceScales.Add(columnConversionConfig.InScale);
                }
            }
            sourceScales.Sort();
            this.cboSimpleSourceScale.Items.Clear();
            this.cboSimpleSourceScale.Items.Add("any");
            for (int index = 0; index < sourceScales.Count; index++)
            {
                this.cboSimpleSourceScale.Items.Add(sourceScales[index].ToString());
            }
            this.cboSimpleSourceScale.SelectedIndex = 0;
            #endregion

            #region Set up Destination Data Type Combo
            this.cboSimpleDestDataType.Items.Clear();
            this.cboSimpleDestDataType.DisplayMember = "CompleteName";
            foreach (DtsDataTypes.DataTypeDescriptionStruct dataTypeDescription in DtsDataTypes.DataTypeDescriptions)
            {
                this.cboSimpleDestDataType.Items.Add(dataTypeDescription);
            }
            this.cboSimpleDestDataType.SelectedItem = DtsDataTypes.GetDataTypeDescriptionStruct(DataType.DT_STR);
            if (this.cboSimpleDestDataType.SelectedIndex < 0)
            {
                this.cboSimpleDestDataType.SelectedIndex = 0;
            }
            #endregion
            #endregion

            #region Setup Complex Conversion Tab
            this.bndConfigColumns.DataSource = this._configuration.CustomProperties.ColumnConversionConfigs;
            this.bndDataTypes.DataSource = DtsDataTypes.DataTypeDescriptions;
            this.bndRowDispositions.DataSource = DtsRowDispositions.DtsRowDispositionDescriptionsWithoutNotUsed;

            this.dgvColumnConfigs.AutoGenerateColumns = false;
            this.dgvColumnConfigs.DataSource = this.bndConfigColumns;
            this.dgvColumnConfigs.Columns.Clear();
            this.dgvColumnConfigs.ShowCellToolTips = true;

            #region Set up columns on data grid
            try
            {
                DataGridViewTextBoxColumn colInLineage = new DataGridViewTextBoxColumn();
                colInLineage.Name = "Input Lineage";
                colInLineage.DataPropertyName = "InLineageID";
                colInLineage.ReadOnly = true;
                this.dgvColumnConfigs.Columns.Add(colInLineage);
                colInLineage.Visible = false;

                DataGridViewTextBoxColumn colName = new DataGridViewTextBoxColumn();
                colName.Name = "Column Name";
                colName.DataPropertyName = "ColumnName";
                colName.ReadOnly = true;
                colName.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                this.dgvColumnConfigs.Columns.Add(colName);

                DataGridViewComboBoxColumn colInDataType = new DataGridViewComboBoxColumn();
                colInDataType.Name = "Input Data Type";
                colInDataType.DataPropertyName = "InDataType";
                colInDataType.DataSource = this.bndDataTypes;
                colInDataType.DisplayMember = "CompleteName";
                colInDataType.ValueMember = "DataType";
                colInDataType.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
                colInDataType.ReadOnly = true;
                colInDataType.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                this.dgvColumnConfigs.Columns.Add(colInDataType);

                DataGridViewTextBoxColumn colInLength = new DataGridViewTextBoxColumn();
                colInLength.Name = "Input Length";
                colInLength.DataPropertyName = "InLength";
                colInLength.ReadOnly = true;
                colInLength.Width = 50;
                this.dgvColumnConfigs.Columns.Add(colInLength);

                DataGridViewTextBoxColumn colInCodePage = new DataGridViewTextBoxColumn();
                colInCodePage.Name = "Input Code Page";
                colInCodePage.DataPropertyName = "InCodePage";
                colInCodePage.ReadOnly = true;
                colInCodePage.Width = 50;
                this.dgvColumnConfigs.Columns.Add(colInCodePage);

                DataGridViewTextBoxColumn colInPrecision = new DataGridViewTextBoxColumn();
                colInPrecision.Name = "Input Precision";
                colInPrecision.DataPropertyName = "InPrecision";
                colInPrecision.ReadOnly = true;
                colInPrecision.Width = 50;
                this.dgvColumnConfigs.Columns.Add(colInPrecision);

                DataGridViewTextBoxColumn colInScale = new DataGridViewTextBoxColumn();
                colInScale.Name = "Input Scale";
                colInScale.DataPropertyName = "InScale";
                colInScale.ReadOnly = true;
                colInScale.Width = 50;
                this.dgvColumnConfigs.Columns.Add(colInScale);

                DataGridViewCheckBoxColumn colWantToConvert = new DataGridViewCheckBoxColumn();
                colWantToConvert.Name = "Conversion Wanted";
                colWantToConvert.DataPropertyName = "WantToConvert";
                colWantToConvert.Width = 70;
                this.dgvColumnConfigs.Columns.Add(colWantToConvert);

                DataGridViewImageColumn colValidIcon = new DataGridViewImageColumn();
                colValidIcon.Name = "Valid";
                colValidIcon.DataPropertyName = "ConversionValidationIcon";
                colValidIcon.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                this.dgvColumnConfigs.Columns.Add(colValidIcon);

                DataGridViewComboBoxColumn colOutDataType = new DataGridViewComboBoxColumn();
                colOutDataType.Name = "Output Data Type";
                colOutDataType.DataPropertyName = "OutDataType";
                colOutDataType.DataSource = this.bndDataTypes;
                colOutDataType.DisplayMember = "CompleteName";
                colOutDataType.ValueMember = "DataType";
                colOutDataType.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox;
                colOutDataType.DisplayStyleForCurrentCellOnly = false;
                colOutDataType.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                this.dgvColumnConfigs.Columns.Add(colOutDataType);

                DataGridViewTextBoxColumn colOutLength = new DataGridViewTextBoxColumn();
                colOutLength.Name = "Output Length";
                colOutLength.DataPropertyName = "OutLength";
                colOutLength.Width = 50;
                this.dgvColumnConfigs.Columns.Add(colOutLength);

                DataGridViewTextBoxColumn colOutCodePage = new DataGridViewTextBoxColumn();
                colOutCodePage.Name = "Output Code Page";
                colOutCodePage.DataPropertyName = "OutCodePage";
                colOutCodePage.Width = 50;
                this.dgvColumnConfigs.Columns.Add(colOutCodePage);

                DataGridViewTextBoxColumn colOutPrecision = new DataGridViewTextBoxColumn();
                colOutPrecision.Name = "Output Precision";
                colOutPrecision.DataPropertyName = "OutPrecision";
                colOutPrecision.Width = 50;
                this.dgvColumnConfigs.Columns.Add(colOutPrecision);

                DataGridViewTextBoxColumn colOutScale = new DataGridViewTextBoxColumn();
                colOutScale.Name = "Output Scale";
                colOutScale.DataPropertyName = "OutScale";
                colOutScale.Width = 50;
                this.dgvColumnConfigs.Columns.Add(colOutScale);

                DataGridViewComboBoxColumn colTruncationRowDisposition = new DataGridViewComboBoxColumn();
                colTruncationRowDisposition.Name = "Behaviour on Truncation Error";
                colTruncationRowDisposition.DataPropertyName = "TruncationRowDisposition";
                colTruncationRowDisposition.DataSource = this.bndRowDispositions;
                colTruncationRowDisposition.DisplayMember = "Description";
                colTruncationRowDisposition.ValueMember = "DTSRowDisposition";
                colTruncationRowDisposition.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox;
                colTruncationRowDisposition.DisplayStyleForCurrentCellOnly = false;
                colTruncationRowDisposition.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                this.dgvColumnConfigs.Columns.Add(colTruncationRowDisposition);

                DataGridViewComboBoxColumn colErrorRowDisposition = new DataGridViewComboBoxColumn();
                colErrorRowDisposition.Name = "Behaviour on Other Conversion Error";
                colErrorRowDisposition.DataPropertyName = "ErrorRowDisposition";
                colErrorRowDisposition.DataSource = this.bndRowDispositions;
                colErrorRowDisposition.DisplayMember = "Description";
                colErrorRowDisposition.ValueMember = "DTSRowDisposition";
                colErrorRowDisposition.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox;
                colErrorRowDisposition.DisplayStyleForCurrentCellOnly = false;
                colErrorRowDisposition.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                this.dgvColumnConfigs.Columns.Add(colErrorRowDisposition);

                DataGridViewCheckBoxColumn colIncludeInOutput = new DataGridViewCheckBoxColumn();
                colIncludeInOutput.Name = "Include in Output";
                colIncludeInOutput.DataPropertyName = "WantToOutput";
                colIncludeInOutput.Width = 60;
                this.dgvColumnConfigs.Columns.Add(colIncludeInOutput);
            }
            #region catch ...
            catch (Exception ex)
            {
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }
            #endregion
            #endregion
            #endregion

            bool oneColumnIsConverting = false;
            foreach (ColumnConversionConfig columnConfig in this._configuration.CustomProperties.ColumnConversionConfigs)
            {
                if (columnConfig.WantToConvert)
                {
                    oneColumnIsConverting = true;
                    break;
                }
            }
            if (oneColumnIsConverting)
            {
                this.tabStyle.SelectedTab = this.tpgComplex;
            }
        }
        #endregion
        #endregion

        #region Control Events
        #region Simple Tab
        #region cboSimpleSourceType
        private void cboSimpleSourceType_SelectedIndexChanged(object sender, EventArgs e)
        {
            DtsDataTypes.DataTypeDescriptionStruct fromType = (DtsDataTypes.DataTypeDescriptionStruct)this.cboSimpleSourceDataType.SelectedItem;

            this.cboSimpleSourceLength.Visible = fromType.HasLength;
            this.cboSimpleSourceCodePage.Visible = fromType.HasCodePage;
            this.cboSimpleSourcePrecision.Visible = fromType.HasPrecision;
            this.cboSimpleSourceScale.Visible = fromType.HasScale;

            this.ShowHeadings();
        }
        #endregion

        #region cboSimpleDestType
        private void cboSimpleDestType_SelectedIndexChanged(object sender, EventArgs e)
        {
            DtsDataTypes.DataTypeDescriptionStruct toType = (DtsDataTypes.DataTypeDescriptionStruct)this.cboSimpleDestDataType.SelectedItem;

            this.cboSimpleDestLength.Visible = toType.HasLength;
            this.cboSimpleDestCodePage.Visible = toType.HasCodePage;
            this.cboSimpleDestPrecision.Visible = toType.HasPrecision;
            this.cboSimpleDestScale.Visible = toType.HasScale;

            this.cboSimpleDestLength.Items.Clear();
            this.cboSimpleDestLength.Items.Add("default");
            this.cboSimpleDestLength.SelectedIndex = 0;
            this.cboSimpleDestCodePage.Items.Clear();
            this.cboSimpleDestCodePage.Items.Add("default");
            this.cboSimpleDestCodePage.SelectedIndex = 0;
            this.cboSimpleDestPrecision.Items.Clear();
            this.cboSimpleDestPrecision.Items.Add("default");
            this.cboSimpleDestPrecision.SelectedIndex = 0;
            this.cboSimpleDestScale.Items.Clear();
            this.cboSimpleDestScale.Items.Add("default");
            this.cboSimpleDestScale.SelectedIndex = 0;

            this.ShowHeadings();
        }
        #endregion

        #region cmdApplySimpleConversion
        private void cmdApplySimpleConversion_Click(object sender, EventArgs e)
        {
            DtsDataTypes.DataTypeDescriptionStruct fromType;
            DtsDataTypes.DataTypeDescriptionStruct toType;
            int columnsConverted = 0;

            try
            {
                fromType = (DtsDataTypes.DataTypeDescriptionStruct)this.cboSimpleSourceDataType.SelectedItem;
                toType = (DtsDataTypes.DataTypeDescriptionStruct)this.cboSimpleDestDataType.SelectedItem;
                foreach (ColumnConversionConfig columnConversionConfig in this._configuration.CustomProperties.ColumnConversionConfigs)
                {
                    if ((columnConversionConfig.InDataType == fromType.DataType)
                        && (!fromType.HasLength || (this.cboSimpleSourceLength.SelectedIndex == 0) || (Convert.ToInt32(this.cboSimpleSourceLength.SelectedItem) == columnConversionConfig.InLength))
                        && (!fromType.HasCodePage || (this.cboSimpleSourceCodePage.SelectedIndex == 0) || (Convert.ToInt32(this.cboSimpleSourceCodePage.SelectedItem) == columnConversionConfig.InCodePage))
                        && (!fromType.HasPrecision || (this.cboSimpleSourcePrecision.SelectedIndex == 0) || (Convert.ToInt32(this.cboSimpleSourcePrecision.SelectedItem) == columnConversionConfig.InPrecision))
                        && (!fromType.HasScale || (this.cboSimpleSourceScale.SelectedIndex == 0) || (Convert.ToInt32(this.cboSimpleSourceScale.SelectedItem) == columnConversionConfig.InScale)))
                    {
                        try
                        {
                            columnConversionConfig.OutDataType = toType.DataType;
                            if (toType.HasLength && ((string)this.cboSimpleDestLength.Text != "default"))
                            {
                                columnConversionConfig.OutLength = Convert.ToInt32(this.cboSimpleDestLength.Text);
                            }
                            if (toType.HasCodePage && ((string)this.cboSimpleDestCodePage.Text != "default"))
                            {
                                columnConversionConfig.OutCodePage = Convert.ToInt32(this.cboSimpleDestCodePage.Text);
                            }
                            if (toType.HasPrecision && ((string)this.cboSimpleDestPrecision.Text != "default"))
                            {
                                columnConversionConfig.OutPrecision = Convert.ToInt32(this.cboSimpleDestPrecision.Text);
                            }
                            if (toType.HasScale && ((string)this.cboSimpleDestScale.Text != "default"))
                            {
                                columnConversionConfig.OutScale = Convert.ToInt32(this.cboSimpleDestScale.Text);
                            }
                            columnsConverted++;
                        }
                        #region catch ...
                        catch (Exception ex)
                        {
                            if (System.Diagnostics.Debugger.IsAttached)
                            {
                                System.Diagnostics.Debugger.Break();
                            }
                        }
                        #endregion
                    }
                }
            }
            #region catch ...
            catch (Exception ex)
            {
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }
            #endregion

            System.Windows.Forms.MessageBox.Show(columnsConverted.ToString() + " columns configured.");
            this.cmdSave.Focus();
        }
        #endregion
        #endregion

        #region Complex Tab
        #region dgvColumnConfigs
        private void dgvColumnConfigs_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            this._configuration.Validate();
            this.bndConfigColumns.ResetBindings(false);
        }

        private void dgvColumnConfigs_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            foreach (DataGridViewRow row in ((DataGridView)sender).Rows)
            {
                row.Cells["Valid"].ToolTipText = ((ColumnConversionConfig)row.DataBoundItem).ConversionValidationMessage;
            }
        }
        #endregion
        #endregion

        #region cmdSave
        private void cmdSave_Click(object sender, EventArgs e)
        {
            this._configuration.ReinitializeMetaData();
            this.Close();
        }
        #endregion
        #endregion

        #region Private Helpers
        private void ShowHeadings()
        {
            if ((this.cboSimpleSourceDataType.SelectedIndex >= 0) && (this.cboSimpleDestDataType.SelectedIndex >= 0))
            {
                DtsDataTypes.DataTypeDescriptionStruct fromType = (DtsDataTypes.DataTypeDescriptionStruct)this.cboSimpleSourceDataType.SelectedItem;
                DtsDataTypes.DataTypeDescriptionStruct toType = (DtsDataTypes.DataTypeDescriptionStruct)this.cboSimpleDestDataType.SelectedItem;

                this.lblLengthSpec.Visible = fromType.HasLength || toType.HasLength;
                this.lblCodePageSpec.Visible = fromType.HasCodePage || toType.HasCodePage;
                this.lblPrecisionSpec.Visible = fromType.HasPrecision || toType.HasPrecision;
                this.lblScaleSpec.Visible = fromType.HasScale || toType.HasScale;
            }
        }
        #endregion
    }
}
